package com.njzxw.fs.commonutil.web.aspect;

import com.njzxw.fs.commonutil.bean.BaseBean;
import com.njzxw.fs.commonutil.bean.BaseUserBean;
import com.njzxw.fs.commonutil.bean.LogBean;
import com.njzxw.fs.commonutil.util.GsonUtil;
import com.njzxw.fs.commonutil.util.StringHelper;
import com.njzxw.fs.commonutil.util.UserUtil;
import com.njzxw.fs.commonutil.web.BaseController;
import com.njzxw.fs.commonutil.web.ReturnMap;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

@Aspect
@Component
public class ParamsValidation extends BaseController {

    public org.slf4j.Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    protected ReturnMap returnMap;

    @Autowired
    protected BaseUserBean baseUserBean;

    @Autowired
    protected UserUtil userUtil;

    @Pointcut("execution(* com.njzxw.*.*..controller..*.*(..))")
    public void aspect() {
    }

    @Around("aspect()")
    public void around(ProceedingJoinPoint jp) {
        long start_time = System.currentTimeMillis();
        String methodName = jp.getSignature().getName();
        Object[] obj = jp.getArgs();
        Object target = jp.getTarget();
        logger = LoggerFactory.getLogger(target.getClass());

        int cnt = obj.length;
        HttpServletResponse response = null;
        HttpServletRequest request = null;
        BindingResult bindingResult = null;
        Throwable ex = null;
        ReturnMap returnMap = null;
        BaseBean baseBean = null;
        Object objs = null;
        boolean isSucc = false;
        String pasams = "";
        long end_time = 0;
        try {

            for (int i = 0; i < cnt; i++) {

                if (obj[i] instanceof HttpServletResponse) {
                    response = (HttpServletResponse) obj[i];
                }

                if (obj[i] instanceof HttpServletRequest) {
                    request = (HttpServletRequest) obj[i];
                }

                if (obj[i] instanceof BindingResult) {
                    bindingResult = (BindingResult) obj[i];

                    if (bindingResult.hasErrors()) {
                        List<ObjectError> ls = bindingResult.getAllErrors();

                        if (!ls.isEmpty()) {
                            returnMap = new ReturnMap();
                            returnMap = returnMap.getErrorReturnMap(ls.get(0).getDefaultMessage());
                        }
                    }

                }

                if (obj[i] instanceof BaseBean) {

                    baseBean = (BaseBean) obj[i];
                    if (baseBean != null) {
//                        logger.debug("beaseBean1:"+baseBean);
////                        ReflectUtil.nullConverStringNull(obj[i]);
//                        logger.debug("beaseBean2:"+baseBean);
                        pasams = baseBean.toString();

                        baseUserBean.setOper_id(baseBean.getOper_id());
                        baseUserBean.setToken(baseBean.getToken());

                        orderBy(baseBean);

//                        manageOrg(baseBean);

                        MDC.put("hascode", String.valueOf(baseBean.hashCode()));
                        MDC.put("pageNum", String.valueOf(baseBean.getPageNum()));
                        MDC.put("pageSize", String.valueOf(baseBean.getPageSize()));
                        MDC.put("orderBy", String.valueOf(baseBean.getOrderBy()));
                        MDC.put("isRole", userUtil.checkRedisRoleExist("1") ? "1" :
                                userUtil.checkRedisRoleExist("2") ? "2" : "3");
                        baseBean.setPageNum(null);
                        baseBean.setPageSize(null);
                        baseBean.setOrderBy(null);

                    }

                }

            }

            if (returnMap == null) {
                objs = jp.proceed();
                isSucc = true;
                if (objs == null) {
                    returnMap = this.returnMap;
                } else {
                    returnMap = (ReturnMap) objs;
                }
                if(baseBean != null){
                    if(returnMap != null){
                        returnMap.setReturnMap("terrace",baseBean.getTerrace());
                    }
                }
            }
        } catch (Throwable throwable) {
            ex = throwable;
        } finally {
            if (baseBean == null) {
                baseBean = new BaseBean();
            }
            end_time = System.currentTimeMillis();
            String state = "";
            if (ex != null) {
                logger.error("执行方法【" + methodName + "】,执行时间：" + (end_time - start_time) + "ms,请求参数信息：" + pasams + "， " +
                        "异常信息: " + ex, ex);
                if (returnMap == null) {
                    returnMap = new ReturnMap();
                    returnMap = returnMap.getErrorReturnMap("可能最近访问人有点多，服务器有点累了，休息一会儿，马上回来。");
                    state = "访问出错";
                }
            } else {
                if (returnMap == null) {
                    returnMap = new ReturnMap();
                    state = "访问异常";
                    logger.error("执行方法【" + methodName + "】,执行时间：" + (end_time - start_time) + "ms,请求参数信息：" + pasams + "， 异常信息: " + ex, ex);
                } else {
                    state = "正常";
                    logger.info("执行方法【" + methodName + "】,执行时间：" + (end_time - start_time) + "ms,请求参数信息：" + pasams +
                            "，返回值：" + returnMap.getReturnMap().toString());
                }
            }

            if (request != null) {
                String url = request.getRequestURI();
                logger.debug("url:" + url);
                LogBean logBean = new LogBean();
                logBean.setOper_url(url);
                logBean.setOper_id(baseBean.getOper_id());
                Map<String, Object> map = userUtil.getUserRep().getLogRemark(logBean);
                logger.debug("logbean:" + logBean.toString());
                if (map != null && !map.isEmpty()) {
                    logBean.setOper_name(StringHelper.get(map, "open_name"));
                    logBean.setOper_remark(StringHelper.get(map, "remark"));
                    logBean.setRequest_params(pasams);
                    logBean.setReturn_str(returnMap.getReturnMap().toString());
                    logBean.setState(state);
                    logBean.setType(baseBean.getRequset_type());
                    userUtil.getUserRep().insertLog(logBean);
                }
            }

            if (objs != null) {
                this.writeJsonDataNoNull(returnMap, response);
            } else {
                if (returnMap != null && !isSucc) {
                    this.writeJsonDataNoNull(returnMap, response);
                }
            }
        }
    }

    public void manageOrg(BaseBean baseBean) {
//        logger.debug("==============="+userUtil.checkRedisManageOrg());
        if (userUtil.checkRedisRoleExist("1")) {//是否是系统管理员，系统管理员直接能查询所有
            baseBean.setManage_org_table_name(null);
            baseBean.setManage_org_table_name_where(null);
        } else if (userUtil.checkRedisRoleExist("2")) {//检查是否是部门管理员
            //获取是那个部门的部门管理员
            String manageOrg = userUtil.checkRedisManageOrg();
            baseBean.setManage_org_table_name(",t_manager_user_org a1");
            baseBean.setManage_org_table_name_where("and a.oper_id = a1.manager_user_id and a1.manager_org_id in (" + (manageOrg.substring(1, manageOrg.length() - 1)) + ") ");
        } else {
            baseBean.setManage_org_table_name(null);
            baseBean.setManage_org_table_name_where(" and a.oper_id = " + baseBean.getOper_id());
        }
    }

    public void writeJsonDataNoNull(ReturnMap returnMap, HttpServletResponse response) {
        try {

            Map data = null;
            if (returnMap != null) {
                data = returnMap.getReturnMap();
            }
            response.setContentType("application/json;charset=utf-8");
            response.setCharacterEncoding("utf-8");

//            JsonConfig jsonConfig = new JsonConfig();
//            PropertyFilter filter = new PropertyFilter() {
//                public boolean apply(Object object, String fieldName, Object fieldValue) {
//                    return null == fieldValue;
//                }
//            };
//
//            jsonConfig.setJsonPropertyFilter(filter);

            response.getWriter().print(GsonUtil.parseObjectToJsonString(data));
//            if (data instanceof Map) {
//                JSONObject.fromObject(data,jsonConfig));
//            } else if (data instanceof List) {
//                response.getWriter().print(JSONArray.fromObject(((List) data),jsonConfig));
//            } else {
//                response.getWriter().print(JSONObject.fromObject(data,jsonConfig));
//            }
        } catch (Exception e) {
            logger.debug("返回值失败：", e);
        }
    }

    @Pointcut("execution(* com.njzxw.*.*..repository..*.*(..))")
    public void aspectSql() {
    }

    @Around("aspectSql()")
    public Object aroundSql(ProceedingJoinPoint jp) {


        String methodName = jp.getSignature().getName();
        Object[] obj = jp.getArgs();
        Object target = jp.getTarget();

        String signature = jp.getSignature().toLongString();
        Class returnTypeClass = ((MethodSignature) jp.getSignature()).getReturnType();
        String returnType = returnTypeClass.getSimpleName();
//        logger.debug("返回类型："+methodName);

        BaseBean baseBean = null;
        int cnt = obj.length;
        for (int i = 0; i < cnt; i++) {
            if (obj[i] instanceof BaseBean) {
                baseBean = (BaseBean) obj[i];
//                logger.debug("baseBeanbaseBeanbaseBean:"+baseBean.toString());
                if (baseBean != null) {
                    String hascode = MDC.get("hascode");
                    if (methodName.toLowerCase().contains("page".toLowerCase()) && (String.valueOf(baseBean.hashCode())).equals(hascode)) {
//                        baseBean.setOrderBy("");
                        String objPageNum = MDC.get("pageNum");
                        String objPageSize = MDC.get("pageSize");
                        String objOrderBy = MDC.get("orderBy");
//                        logger.debug("???????====2=:"+objPageNum+"--"+objPageSize+"--"+objOrderBy);
                        if (baseBean.getPageNum() == null && objPageNum != null && !"null".equals(objPageNum)) {
                            baseBean.setPageNum(objPageNum == null ? null : Integer.valueOf(objPageNum));
                        } else if (StringUtils.isBlank(objPageNum) && !StringUtils.isBlank(objPageSize)) {
                            baseBean.setPageNum(1);
                        }

                        if (baseBean.getPageSize() == null && objPageSize != null && !"null".equals(objPageSize)) {
                            baseBean.setPageSize(objPageNum == null ? null : Integer.valueOf(objPageSize));
                        }

                        if (StringUtils.isBlank(baseBean.getOrderBy()) && objOrderBy != null && !"null".equals(objOrderBy)) {
                            baseBean.setOrderBy(objOrderBy == null ? null : String.valueOf(objOrderBy));
                        }

//                        logger.debug("???????====1=:"+StringUtils.isNotBlank(baseBean.getOrderKey()));
                        if (StringUtils.isNotBlank(baseBean.getOrderKey())) {
                            orderBy(baseBean);
                        }

                    } else if (methodName.toLowerCase().contains("page".toLowerCase())) {
                        orderBy(baseBean);
                    }
                    if (methodName.toLowerCase().contains("manageorg".toLowerCase())) {

                        String isRole = MDC.get("isRole");
                        if ("1".equals(isRole)) {//是否是系统管理员，系统管理员直接能查询所有
                            baseBean.setManage_org_table_name(null);
                            baseBean.setManage_org_table_name_where(null);
                        } else if ("2".equals(isRole)) {//检查是否是部门管理员
                            //获取是那个部门的部门管理员
                            String manageOrg = userUtil.checkRedisManageOrg();
                            baseBean.setManage_org_table_name(",t_manager_user_org a1");
                            baseBean.setManage_org_table_name_where("and a.oper_id = a1.manager_user_id and a1" +
                                    ".manager_org_id in (" + (manageOrg.substring(1, manageOrg.length() - 1)) + ") ");
                        } else {
                            baseBean.setManage_org_table_name(null);
                            baseBean.setManage_org_table_name_where(" and a.oper_id = " + baseBean.getOper_id());
                        }
                    }
                }
                logger.debug("请求执行sqlbebean参数值:" + baseBean.toString());
            }
        }

        try {
            return jp.proceed();
        } catch (Throwable throwable) {
            logger.error("执行sql出现错误：", throwable);
            if (returnType.equals("List")) {
                return null;
            } else if (returnType.equals("Map")) {
                return null;
            } else if (returnType.equals("String")) {
                return null;
            } else if (returnType.equals("Int")) {
                return -1;
            } else if (returnType.equals("Integer")) {
                return -1;
            }
        }
        return null;
    }

    public void orderBy(BaseBean baseBean) {
        logger.debug("StringUtils.isBlank(baseBean.getOrderKey()) && StringUtils.isBlank(baseBean.getOrderBy()):" + (StringUtils.isBlank(baseBean.getOrderKey()) && StringUtils.isBlank(baseBean.getOrderBy())));
        if (StringUtils.isBlank(baseBean.getOrderKey()) && StringUtils.isBlank(baseBean.getOrderBy())) {
            baseBean.setOrderBy(" a.oper_date desc ");
        } else {
            if (StringUtils.isBlank(baseBean.getOrderBy())) {
                baseBean.setOrderBy(baseBean.getOrderKey() + "  " + (StringUtils.isBlank(baseBean.getOrderRule()) ? "" : baseBean.getOrderRule()));
            }
        }
    }

}
